// Thud - a dynamic object-oriented language
// Copyright (C) 2009,2010 David H. Hovemeyer <david.hovemeyer@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

/*
 * Constant.cpp
 *
 *  Created on: Dec 1, 2009
 *      Author: dhovemey
 */

#include "util/DataInputStream.h"
#include "util/DataOutputStream.h"
#include "vm/ClassFormatException.h"
#include "vm/ConstantInt32.h"
#include "vm/ConstantString.h"
#include "vm/ConstantSymbol.h"
#include "vm/ConstantClass.h"
#include "vm/ConstantBoolean.h"
#include "vm/Constant.h"

Constant::Constant(ConstantType type)
	: m_type(type)
{

}

Constant::~Constant()
{

}

void Constant::writeConstant(DataOutputStream *out, const Constant *c)
{
	out->writeByte(c->getTagByte());
	c->write(out);
}

Constant* Constant::readConstant(DataInputStream *in)
{
	uint8_t tag = in->readByte();

	Constant *c;

	switch (tag) {
	case CONSTANT_I32_TAG:
		c = new ConstantInt32(); break;
	case CONSTANT_STRING_TAG:
		c = new ConstantString(); break;
	case CONSTANT_SYMBOL_TAG:
		c = new ConstantSymbol(); break;
	case CONSTANT_CLASS_TAG:
		c = new ConstantClass(); break;
	case CONSTANT_BOOLEAN_TAG:
		c = new ConstantBoolean(); break;
	default:
		throw ClassFormatException(L"unknown constant type");
	}

	c->read(in);

	return c;
}

bool Constant::lessThan(const Constant *left, const Constant *right)
{
	if (left->getType() != right->getType()) {
		return left->getType() < right->getType();
	} else {
		return left->compare(right);
	}
}
